#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : book_modules.py
# @Author: Xuhao
# @Date  : 2018/3/15
# @Desc  : 

from app.Sql.SQLSession import Base,DataBaseConnector
from app.Modules.booksource_modules import BookSource

from sqlalchemy import Column, String
from sqlalchemy.orm import relationship
import json

from sqlalchemy.ext.declarative import DeclarativeMeta
from sqlalchemy.sql.expression import func


#定义小说信息表
class NoverInfo(Base):
    __tablename__ = 'NoverInfo'
    __table_args__ = {"extend_existing": True}

    novelName = Column(String(128))
    noveAuthor = Column(String(18))
    noveUrl = Column(String(128))
    noveStatus = Column(String(1))
    noveCategory = Column(String(16))
    noveID = Column(String(32), primary_key=True)
    novelastUpdataTime = Column(String(32))
    noveAbstract = Column(String(256))
    noveImageUrl = Column(String(128))

    bookUrls = relationship('BookSource', order_by='BookSource.bookUrl')


    # 在modules 中写好查询条件, 使用时直接调用

    @classmethod
    def select_bookToday(cls, count):
        '''
        小说推荐
        :return:
        '''
        connect = DataBaseConnector()

        session =  connect.get_session()

        bookinfo = session.query(NoverInfo).order_by(func.random()).limit(count).all()

        #connect.close()
        return json.dumps(bookinfo, cls=new_alchemy_encoder(False, 'bookUrls'))


    @classmethod
    def select_book(cls, bookName):
        '''
        收索小说
        :param bookName:
        :return:
        '''

        connect = DataBaseConnector()

        session = connect.get_session()

        bookinfo = session.query(NoverInfo).filter(NoverInfo.novelName.like('%' + bookName + '%')).all()

        connect.close()

        return json.dumps(bookinfo, cls=new_alchemy_encoder(False, 'bookUrls'))


    @classmethod
    def select_booksWithRank(cls, bookfl='全部', startID=0, count=10):
        '''
        根据排行榜获取书籍列表
        :return:
        '''

        if bookfl == "全部":
            sql = "select  p.* from " \
                  "(select b.*,IFNULL((select clickCount from bookClickRankList where bookID=b.noveID ),0) " \
                  "as clickCount from NoverInfo as b where b.noveUrl is NOT NULL ) " \
                  "as p order by p.clickCount DESC limit %s,%s " % (startID, count)
            # sql = "select * from NoverInfo where noveUrl is not null ORDER BY novelastUpdataTime DESC limit %s,%s " % (startID, count)
        else:
            sql = "select  p.* from " \
                  "(select b.*,IFNULL((select clickCount from bookClickRankList where bookID=b.noveID ),0) " \
                  "as clickCount from NoverInfo as b where b.noveCategory='%s' and b.noveUrl is NOT NULL ) " \
                  "as p order by p.clickCount DESC limit %s,%s " % (bookfl, startID, count)

        connect = DataBaseConnector()

        session = connect.get_session()

        booklist = session.execute(sql)

        factory = DbRowFactory.fromSqlAlchemyResultProxy(resultProxy=booklist, rowClassFullName="app.Modules.book_modules.NoverInfo")

        connect.close()
        return json.dumps(factory.fetchAllRowObjects(), cls=new_alchemy_encoder(False, 'bookUrls')) #'bookUrls'



    @classmethod
    def select_booksWithGoddess(cls, type, startID, count):
        '''
        根据排行榜获取书籍列表
        :return:
        '''

        if type == 0: #男神

            sql = "select  p.* from " \
                  "(select b.*,IFNULL((select clickCount from bookClickRankList where bookID=b.noveID ),0) " \
                  "as clickCount from NoverInfo as b where (b.noveCategory='玄幻魔法' or b.noveCategory='武侠修真') and b.noveUrl is NOT NULL ) " \
                  "as p order by p.clickCount DESC limit %s,%s " % (startID, count)

        elif type == 1:# 女神

            sql = "select  p.* from " \
                  "(select b.*,IFNULL((select clickCount from bookClickRankList where bookID=b.noveID ),0) " \
                  "as clickCount from NoverInfo as b where (b.noveCategory='都市言情' or b.noveCategory='其他类型' or b.noveCategory='散文诗词' ) " \
                  "and b.noveUrl is NOT NULL ) " \
                  "as p order by p.clickCount DESC limit %s,%s " % (startID, count)
        else: #总榜

            sql = "select  p.* from " \
                  "(select b.*,IFNULL((select clickCount from bookClickRankList where bookID=b.noveID ),0) " \
                  "as clickCount from NoverInfo as b where b.noveUrl is NOT NULL ) " \
                  "as p order by p.clickCount DESC limit %s,%s " % (startID, count)

        connect = DataBaseConnector()

        session = connect.get_session()

        booklist = session.execute(sql)
        factory = DbRowFactory.fromSqlAlchemyResultProxy(resultProxy=booklist, rowClassFullName="app.Modules.book_modules.NoverInfo")
        connect.close()
        return json.dumps(factory.fetchAllRowObjects(), cls=new_alchemy_encoder(False, 'bookUrls'))


    @classmethod
    def fetchBookDetai(cls, bookID):
        '''
        根据BOOKID 获取书籍详情
        :param bookID:
        :return:
        '''
        connect = DataBaseConnector()

        session = connect.get_session()

        bookinfo = session.query(NoverInfo).filter(NoverInfo.bookUrls.any(BookSource.bookID == bookID)).first()
        connect.close()
        return json.dumps(bookinfo, cls=new_alchemy_encoder(False, 'bookUrls'))



def new_alchemy_encoder(revisit_self=False, fields_to_expand=[]):
    _visited_objs = []

    class AlchemyEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj.__class__, DeclarativeMeta):
                # don't re-visit self
                if revisit_self:
                    if obj in _visited_objs:
                        return None
                    _visited_objs.append(obj)

                # go through each field in this SQLalchemy class
                fields = {}
                for field in [x for x in dir(obj) if
                              not x.startswith('_') and x != 'metadata' and hasattr(obj.__getattribute__(x),
                                                                                    '__call__') == False]:
                    val = obj.__getattribute__(field)

                    # is this field another SQLalchemy object, or a list of SQLalchemy objects?
                    if isinstance(val.__class__, DeclarativeMeta) or (
                                    isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__,
                                                                                          DeclarativeMeta)):
                        # unless we're expanding this field, stop here
                        if field not in fields_to_expand:
                            # not expanding this field: set it to None and continue
                            fields[field] = None
                            continue

                    fields[field] = val
                # a json-encodable dict
                return fields

            return json.JSONEncoder.default(self, obj)

    return AlchemyEncoder

from app.common.pyDbRowFactory import  DbRowFactory
if __name__ == "__main__":


    # bookID = '00f7fcf918c44caf9954a5e50d685b2a'
    # bookinfo = session.query(NoverInfo).filter(NoverInfo.bookUrls.any(BookSource.bookID == bookID)).first()
    # print(json.dumps(bookinfo, cls=new_alchemy_encoder(False, 'bookUrls')))

    connect = DataBaseConnector()

    session = connect.get_session()

    bookname = '永夜君王'
    bookinfo = session.query(NoverInfo).filter(NoverInfo.novelName.like('%' + bookname + '%')).all()
    print(json.dumps(bookinfo, cls=new_alchemy_encoder(False, 'bookUrls')))

    # booklist = NoverInfo.select_booksWithRank(count=1)
    # factory = DbRowFactory.fromSqlAlchemyResultProxy(resultProxy=booklist,rowClassFullName='NoverInfo')
    # print(json.dumps(factory.fetchAllRowObjects(), cls=new_alchemy_encoder(False, 'bookUrls')))


   # print(booklist)


    # sql = Sqlhelper()
    #
    # ret = sql.fetchBookList(categoryStr='全部', startID=0,count=5)

